package ec;

import java.util.HashMap;
import java.util.List;

public abstract class Solution {
	protected HashMap<String, Object> _info = new HashMap<String,Object>();
	
	private static int _last_id = 0;

	protected double _fitness = 0;

	protected int _id = 0;
	protected int _parentA_id = 0;
	protected int _parentB_id = 0;

	protected String _solution_string;

	protected Solution() {
		_id = (++_last_id);
	}
	
	public abstract String getSolutionString();

	public HashMap<String,Object> getInfo() {
		return _info;
	}
	
	/**
	 * Given a second solution, perform crossover with it and return the two
	 * resulting children.
	 * 
	 * @param solutionB
	 * @return
	 */
	public abstract List<Solution> crossover(Solution solutionB);

	/**
	 * Creates a mutated copy of this solution.
	 * 
	 * @return
	 */
	public abstract Solution mutate();

	/**
	 * Create an exact copy of this solution.
	 * 
	 * @return
	 */
	public abstract Solution duplicate();

	/**
	 * Return the IDs of the parents used to create this solution. If the
	 * solution was created by mutation it will only have one parent.
	 * 
	 * @return
	 */
	public int[] getParentsID() {
		return new int[] { _parentA_id, _parentB_id };
	}

	/**
	 * Set the parents of this solution.
	 * 
	 * @param parentA
	 * @param parentB
	 */
	public void setParentsID(Solution parentA, Solution parentB) {
		if (parentA != null) {
			_parentA_id = parentA.getID();
		}

		if (parentB != null) {
			_parentB_id = parentB.getID();
		}
		else {
			_parentB_id = 0;
		}
	}

	/**
	 * Get the unique ID of this solution.
	 * 
	 * @return
	 */
	public int getID() {
		return _id;
	}

	/**
	 * Get the fitness of this solution.
	 * 
	 * @return
	 */
	public double getFitness() {
		return _fitness;
	}

	/**
	 * Adjust the fitness by the given delta. fitness = fitness + delta.
	 * 
	 * @param fitness_delta
	 */
	public void adjustFitness(double fitness_delta) {
		_fitness += fitness_delta;
	}

	/**
	 * Set the fitness of this solution.
	 * 
	 * @param fitness
	 */
	public void setFitness(double fitness) {
		_fitness = fitness;
	}

	public void setSolutionString(String string) {
		_solution_string = string;
	}
}
